package main

import (
	"errors"
	"hedge/persistence"
	"strconv"
	"time"

	"gitee.com/hacker61/go-binance/v2"
	"gitee.com/hacker61/go-binance/v2/futures"
)

type SymbolBookTicker struct {
	Symbol            string
	BinanceBookTicker *binance.WsBookTickerEvent
	FuturesBookTicker *futures.WsBookTickerEvent
	Premium           float64
	AntiPremium       float64
}

func (st *SymbolBookTicker) CalcPremium() {
	if st.BinanceBookTicker == nil || st.FuturesBookTicker == nil {
		st.Premium = -1
		st.AntiPremium = 1
	} else {
		st.Premium = -1
		st.AntiPremium = 1
		futuresBestBidPrice, err := strconv.ParseFloat(st.FuturesBookTicker.BestBidPrice, 64)
		if err != nil {
			Error.Printf("FuturesBookTicker.BestBidPrice is not Float64, err = %v\n", err)
			return
		}
		binanceBestAskPrice, err := strconv.ParseFloat(st.BinanceBookTicker.BestAskPrice, 64)
		if err != nil {
			Error.Printf("BinanceBookTicker.BestAskPrice is not Float64, err = %v\n", err)
			return
		}
		st.Premium = (futuresBestBidPrice - binanceBestAskPrice) / binanceBestAskPrice
		//Debug.Printf("Symbol: %s, BinanceBookTicker: %v, FuturesBookTicker: %v, Premium: %v\n", st.Symbol, st.BinanceBookTicker, st.FuturesBookTicker, st.Premium)
		futuresBestAskPrice, err := strconv.ParseFloat(st.FuturesBookTicker.BestAskPrice, 64)
		if err != nil {
			Error.Printf("FuturesBookTicker.BestAskPrice is not Float64, err = %v\n", err)
			return
		}
		binanceBestBidPrice, err := strconv.ParseFloat(st.BinanceBookTicker.BestBidPrice, 64)
		if err != nil {
			Error.Printf("BinanceBookTicker.BestBidPrice is not Float64, err = %v\n", err)
			return
		}
		st.AntiPremium = (futuresBestAskPrice - binanceBestBidPrice) / binanceBestBidPrice
	}
}

type SymbolBookTickerSlice []SymbolBookTicker

func (st SymbolBookTickerSlice) Len() int {
	return len(st)
}

func (st SymbolBookTickerSlice) Less(i, j int) bool {
	return st[i].Premium < st[j].Premium
}

func (st SymbolBookTickerSlice) Swap(i, j int) {
	st[i], st[j] = st[j], st[i]
}

func (st SymbolBookTickerSlice) SymbolIndex(symbol string) int {
	for k, v := range st {
		if v.Symbol == symbol {
			return k
		}
	}
	return -1
}

type SymbolArbitrage struct {
	client        *binance.Client
	futuresClient *futures.Client

	Symbol         string
	BookTicker     SymbolBookTicker              //当前市场持仓信息
	symbolPosition persistence.ArbitragePosition //持仓信息

	binanceBookTickerC          chan *binance.WsBookTickerEvent
	futuresBookTickerC          chan *futures.WsBookTickerEvent
	chanBinanceFilledOrder      chan binance.WsExecutionReportEvent
	chanFuturesOrderTradeUpdate chan futures.WsOrderTradeUpdate

	limitOrderTimer *time.Timer
	chanFinish      chan struct{}

	binanceLimitOrderId      int64
	futuresLimitOrderId      int64
	binanceAntiLimitOrderId  int64
	futuresAntiLimitOrderId  int64
	subStateBinanceExecQty   float64 //子状态变更时存下的记录
	subStateBinanceExecPrice float64 //子状态变更时存下的记录
	subStateFuturesExecQty   float64 //子状态变更时存下的记录
	subStateFuturesExecPrice float64 //子状态变更时存下的记录
	dPremiumStage            float64

	stateMachine *StateMachine
}

func NewSymbolArbitrage(symbol string, client *binance.Client, futuresClient *futures.Client) *SymbolArbitrage {
	symbolArbitrage := new(SymbolArbitrage)
	symbolArbitrage.Symbol = symbol
	symbolArbitrage.BookTicker.Symbol = symbol
	symbolArbitrage.client = client
	symbolArbitrage.futuresClient = futuresClient
	symbolArbitrage.binanceBookTickerC = make(chan *binance.WsBookTickerEvent, 1)
	symbolArbitrage.futuresBookTickerC = make(chan *futures.WsBookTickerEvent, 1)
	symbolArbitrage.chanBinanceFilledOrder = make(chan binance.WsExecutionReportEvent, 1)
	symbolArbitrage.chanFuturesOrderTradeUpdate = make(chan futures.WsOrderTradeUpdate, 1)
	symbolArbitrage.stateMachine = NewStateMachine(symbolArbitrage)
	symbolArbitrage.stateMachine.ChangeState(State_NotPosition)
	// 防止StartRuntine时崩溃
	symbolArbitrage.limitOrderTimer = time.NewTimer(1 * time.Nanosecond)
	<-symbolArbitrage.limitOrderTimer.C
	symbolArbitrage.chanFinish = make(chan struct{}, 1)

	return symbolArbitrage
}

func (sa *SymbolArbitrage) StartRuntine() {
	for {
		var binanceBookTicker *binance.WsBookTickerEvent
		var futuresBookTicker *futures.WsBookTickerEvent
		var binanceFilledOrder binance.WsExecutionReportEvent
		var futuresOrderTradeUpdate futures.WsOrderTradeUpdate
		select {
		case binanceBookTicker = <-sa.binanceBookTickerC:
			//Info.Println(binanceBookTicker)
			sa.ProcessWithBinanceChange(binanceBookTicker)
		case futuresBookTicker = <-sa.futuresBookTickerC:
			//Info.Println(futuresBookTicker)
			sa.ProcessWithFuturesChange(futuresBookTicker)
		case binanceFilledOrder = <-sa.chanBinanceFilledOrder:
			Info.Println(binanceFilledOrder)
			sa.ProcessWithBinanceFilledOrder(binanceFilledOrder)
		case futuresOrderTradeUpdate = <-sa.chanFuturesOrderTradeUpdate:
			Info.Println(futuresOrderTradeUpdate)
			sa.ProcessWithFuturesOrderTradeUpdate(futuresOrderTradeUpdate)
		case <-sa.limitOrderTimer.C:
			Info.Println("timeout")
			sa.ProcessTimeout()
		case <-sa.chanFinish:
			Info.Println("finish")
			return
		}
	}
}

func (sa *SymbolArbitrage) ProcessWithBinanceChange(binanceBookTicker *binance.WsBookTickerEvent) {
	sa.BookTicker.BinanceBookTicker = binanceBookTicker
	sa.BookTicker.CalcPremium()
	sa.processSymbolBookTicker()
}

func (sa *SymbolArbitrage) ProcessWithFuturesChange(futuresBookTicker *futures.WsBookTickerEvent) {
	sa.BookTicker.FuturesBookTicker = futuresBookTicker
	sa.BookTicker.CalcPremium()
	sa.processSymbolBookTicker()
}

func (sa *SymbolArbitrage) ProcessWithBinanceFilledOrder(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	if sa.stateMachine.State == State_LimitOrderCreated {
		if sa.stateMachine.SubState == SubState_Init {
			sa.subProcess_BinanceFilled_NotPosition_InitSubState(tmpBinanceFilledOrder)
		} else if sa.stateMachine.SubState == SubState_BinanceAntiCreated {
			sa.subProcess_BinanceFilled_NotPosition_BinanceAntiCreatedSubState(tmpBinanceFilledOrder)
		} else if sa.stateMachine.SubState == SubState_FuturesAntiCreated {
			sa.subProcess_BinanceFilled_NotPosition_FuturesAntiCreatedSubState(tmpBinanceFilledOrder)
		} else {
			Warning.Printf("SubState is %v\n", sa.stateMachine.SubState)
		}
	} else if sa.stateMachine.State == State_AntiLimitOrderCreated {
		if sa.stateMachine.SubState == SubState_Init {
			sa.subProcess_BinanceFilled_Position_InitSubState(tmpBinanceFilledOrder)
		} else if sa.stateMachine.SubState == SubState_BinanceAntiCreated {
			sa.subProcess_BinanceFilled_Position_BinanceAntiCreatedSubState(tmpBinanceFilledOrder)
		} else if sa.stateMachine.SubState == SubState_FuturesAntiCreated {
			sa.subProcess_BinanceFilled_Position_FuturesAntiCreatedSubState(tmpBinanceFilledOrder)
		} else {
			Error.Printf("Unknown SubState %v\n", sa.stateMachine.SubState)
		}
	}
}

func (sa *SymbolArbitrage) ProcessWithFuturesOrderTradeUpdate(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if sa.stateMachine.State == State_LimitOrderCreated {
		if sa.stateMachine.SubState == SubState_Init {
			sa.subProcess_FuturesFilled_NotPosition_InitSubState(tmpFuturesUserData)
		} else if sa.stateMachine.SubState == SubState_FuturesAntiCreated {
			sa.subProcess_FuturesFilled_NotPosition_FuturesAntiCreatedSubState(tmpFuturesUserData)
		} else if sa.stateMachine.SubState == SubState_BinanceAntiCreated {
			sa.subProcess_FuturesFilled_NotPosition_BinanceAntiCreatedSubState(tmpFuturesUserData)
		} else {
			Warning.Printf("SubState is %v\n", sa.stateMachine.SubState)
		}
	} else if sa.stateMachine.State == State_AntiLimitOrderCreated {
		if sa.stateMachine.SubState == SubState_Init {
			sa.subProcess_FuturesFilled_Position_InitSubState(tmpFuturesUserData)
		} else if sa.stateMachine.SubState == SubState_BinanceAntiCreated {
			sa.subProcess_FuturesFilled_Position_BinanceAntiCreatedSubState(tmpFuturesUserData)
		} else if sa.stateMachine.SubState == SubState_FuturesAntiCreated {
			sa.subProcess_FuturesFilled_Position_FuturesAntiCreatedSubState(tmpFuturesUserData)
		} else {
			Error.Printf("Unknown SubState %v\n", sa.stateMachine.SubState)
		}
	}
}

func (sa *SymbolArbitrage) ProcessTimeout() {
	if sa.stateMachine.State == State_LimitOrderCreated {
		sa.timeoutNotPosition()
	} else if sa.stateMachine.State == State_AntiLimitOrderCreated {
		sa.timeoutPosition()
	} else {
		Warning.Printf("Unknown state %v in timeout.\n", sa.stateMachine.State)
	}
}

//
func (sa *SymbolArbitrage) changeState2Position(symbol string, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice float64) {
	sa.dPremiumStage = 0.0

	ppersistence.InsertArbitragePosition(symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
	//symbolPosition = persistence.ArbitragePosition{Symbol: limitOrderSymbolBookTicker.Symbol, SpotCount: binanceExecQty, FutureCount: futuresExecQty, SpotPrice: binanceExecPrice, FuturePrice: futuresExecPrice}
	sp := persistence.ArbitragePosition{Symbol: symbol, SpotCount: binanceExecQty, FutureCount: futuresExecQty, SpotPrice: binanceExecPrice, FuturePrice: futuresExecPrice}

	err := sa.ChangeState2Position(sp)
	if err != nil {
		Error.Println(err)
	}
}

func (sa *SymbolArbitrage) ChangeState2Position(sp persistence.ArbitragePosition) error {
	err := sa.stateMachine.ChangeState(State_Position, sp)
	return err
}

//
func (sa *SymbolArbitrage) processSymbolBookTicker() {
	if sa.stateMachine.State == State_NotPosition {
		if sa.BookTicker.Premium > conf.CreatePremium {
			sa.dPremiumStage = float64(int((sa.BookTicker.Premium-conf.CreatePremium)/conf.PremiumStage))*conf.PremiumStage + conf.CreatePremium
			Info.Printf("sa.BookTicker = %v, sa.dPremiumStage = %v\n", sa.BookTicker, sa.dPremiumStage)
			err := sa.stateMachine.ChangeState(State_OneCanCreatePosition)
			if err != nil {
				Error.Println(err)
			}
		}
	} else if sa.stateMachine.State == State_OneCanCreatePosition {
		if sa.BookTicker.Premium > sa.dPremiumStage && sa.BookTicker.Premium < conf.GreatCreatePremium {
			sa.dPremiumStage = float64(int((sa.BookTicker.Premium-conf.CreatePremium)/conf.PremiumStage))*conf.PremiumStage + conf.CreatePremium
			Info.Printf("sa.BookTicker = %v, dPremiumStage = %v\n", sa.BookTicker, sa.dPremiumStage)
		} else if sa.BookTicker.Premium < conf.CreatePremium {
			Info.Printf("bOneCanCreatePosition stop, sa.BookTicker = %v\n", sa.BookTicker)

			err := sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			Info.Printf("Create Arbitrage Order, sa.BookTicker %v, sa.BookTicker.BinanceBookTicker %v, sa.BookTicker.FuturesBookTicker %v",
				sa.BookTicker, *(sa.BookTicker.BinanceBookTicker), *(sa.BookTicker.FuturesBookTicker))
			//createArbitrageOrder_v2(conf.QuoteOrderQty, sa.BookTicker.BinanceBookTicker.BestAskPrice, sa.BookTicker.FuturesBookTicker.BestBidPrice, sa.BookTicker.Symbol)
			binanceOrderId, futuresOrderId, binanceErr, futuresErr := createArbitrageLimitOrder(conf.QuoteOrderQty,
				sa.BookTicker.BinanceBookTicker.BestAskPrice, sa.BookTicker.FuturesBookTicker.BestBidPrice, sa.BookTicker.Symbol)
			if binanceErr == nil && futuresErr == nil {
				//bWaitLimitOrder = true
				if sa.limitOrderTimer == nil {
					sa.limitOrderTimer = time.NewTimer(5 * time.Second)
				} else {
					select {
					case <-sa.limitOrderTimer.C:
						sa.limitOrderTimer.Reset(5 * time.Second)
					default:
						sa.limitOrderTimer.Reset(5 * time.Second)
					}
				}

				// 将当前溢价保存起来
				sa.dPremiumStage = sa.BookTicker.Premium

				err := sa.stateMachine.ChangeState(State_LimitOrderCreated, binanceOrderId, futuresOrderId)
				if err != nil {
					Error.Println(err)
				}
			}
		}
	} else if sa.stateMachine.State == State_Position {
		if sa.BookTicker.AntiPremium < conf.ClosePremium {
			sa.dPremiumStage = float64(int((sa.BookTicker.AntiPremium-conf.ClosePremium)/conf.PremiumStage))*conf.PremiumStage + conf.ClosePremium
			Info.Printf("sa.BookTicker.Premium = %v, sa.dPremiumStage = %v\n", sa.BookTicker.AntiPremium, sa.dPremiumStage)

			err := sa.stateMachine.ChangeState(State_OneCanClosePosition)
			if err != nil {
				Error.Println(err)
			}
		}
	} else if sa.stateMachine.State == State_OneCanClosePosition {
		if sa.BookTicker.AntiPremium < sa.dPremiumStage && sa.BookTicker.AntiPremium > conf.GreatClosePremium {
			sa.dPremiumStage = float64(int((sa.BookTicker.AntiPremium-conf.ClosePremium)/conf.PremiumStage))*conf.PremiumStage + conf.ClosePremium
		} else if sa.BookTicker.AntiPremium > conf.ClosePremium {
			Info.Printf("sa.BookTicker.AntiPremium = %v, sa.dPremiumStage = %v\n", sa.BookTicker.AntiPremium, sa.dPremiumStage)
			err := sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			Info.Printf("Close Arbitrage Order, sa.BookTicker %v, sa.BookTicker.BinanceBookTicker %v, sa.BookTicker.FuturesBookTicker %v",
				sa.BookTicker, *(&sa.BookTicker.BinanceBookTicker), *(&sa.BookTicker.FuturesBookTicker))
			// 达到平仓条件，平仓
			binanceOrderId, futuresOrderId, binanceErr, futuresErr := closeArbitrageLimitOrder(sa.symbolPosition.SpotCount,
				sa.symbolPosition.FutureCount, sa.BookTicker.BinanceBookTicker.BestBidPrice, sa.BookTicker.FuturesBookTicker.BestAskPrice, sa.symbolPosition.Symbol)
			if binanceErr == nil && futuresErr == nil {
				if sa.limitOrderTimer == nil {
					sa.limitOrderTimer = time.NewTimer(5 * time.Second)
				} else {
					select {
					case <-sa.limitOrderTimer.C:
						sa.limitOrderTimer.Reset(5 * time.Second)
					default:
						sa.limitOrderTimer.Reset(5 * time.Second)
					}
				}

				err := sa.stateMachine.ChangeState(State_AntiLimitOrderCreated, binanceOrderId, futuresOrderId)
				if err != nil {
					Error.Println(err)
				}
			}
		}
	}
}

// 子状态变化处理，当前币种未持仓
func (sa *SymbolArbitrage) subProcess_BinanceFilled_NotPosition_InitSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	_, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance Order Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	// 判断当前合约单状态，如果此时已经成交，则可以直接转为持仓，如果此时部分成交，则等待全部成交即可
	_, futuresExecQty, futuresExecPrice, futuresStatus, _ := getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
	if futuresStatus == futures.OrderStatusTypeFilled {
		sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		return
	} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
		Info.Printf("FuturesOrder %v is Partially Filled. Please wait\n", sa.futuresLimitOrderId)
		return
	}

	bFuturesMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	futuresBestBidPrice, err := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestBidPrice, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestBidPrice is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}
	futuresBestBidQty, err := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestBidQty, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestBidQty is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}

	if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.GreatCreatePremium &&
		futuresBestBidPrice*futuresBestBidQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bFuturesMarket = true
	} else {
		bFuturesMarket = false
	}

	if bFuturesMarket {
		// 创建合约市价单，并取消合约挂单
		// 取消当前合约限价单
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(sa.BookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty)
		if err != nil {
			Error.Println(err)
			bFuturesMarket = false
		} else {
			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		}
	}
	if !bFuturesMarket {
		var priceBinancePrecision, priceFuturesPrecision int
		exchangeInfo, bOK := symbolExchangeInfos[sa.BookTicker.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		priceBinancePrecision = exchangeInfo.SpotPricePrecision
		priceFuturesPrecision = exchangeInfo.FuturesPricePrecision
		sBinanceAntiPrice := strconv.FormatFloat(binanceExecPrice*(1+conf.CreatePremium), 'f', priceBinancePrecision, 64)
		sFuturesAntiPrice := strconv.FormatFloat(binanceExecPrice*(1+sa.dPremiumStage-0.002), 'f', priceFuturesPrecision, 64) // 减少0.002下单
		Info.Println(sBinanceAntiPrice, sFuturesAntiPrice)
		antiOrderId, err := createBinanceSellLimitOrder(sa.BookTicker.Symbol, sBinanceAntiPrice, binanceExecQty)
		if err != nil {
			Error.Println(err)
			antiOrderId = 0
		}
		var antiFuturesOrderId int64
		antiFuturesOrderId = 0
		if sa.dPremiumStage-conf.CreatePremium > 0.002 {
			antiFuturesOrderId, err = createFuturesSellLimitOrder(sa.BookTicker.Symbol, sFuturesAntiPrice, conf.QuoteOrderQty)
			if err != nil {
				Error.Println(err)
				antiFuturesOrderId = 0
			}
		}
		sa.stateMachine.ChangeSubState(SubState_BinanceAntiCreated, antiOrderId, antiFuturesOrderId, binanceExecQty, binanceExecPrice)
	}
}

func (sa *SymbolArbitrage) subProcess_BinanceFilled_NotPosition_BinanceAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	if sa.binanceAntiLimitOrderId == 0 {
		Warning.Println("binanceAntiLimitOrderId == 0")
		return
	}
	_, _, _, binanceStatus, binanceErr := getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance AntiOrder Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	var futuresExecQty, futuresExecQuoteQty, futuresExecPrice, futuresExecQty2, futuresExecQuoteQty2, futuresExecPrice2 float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	// 将合约单取消
	if sa.futuresLimitOrderId != 0 {
		futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将创建的合约适配单取消
	if sa.futuresAntiLimitOrderId != 0 {
		futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2, futuresStatus2, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	// 如果合约单有成交，平掉
	if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
		if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
			if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				futuresExecQty += futuresExecQty2
				futuresExecQuoteQty += futuresExecQuoteQty2
				futuresExecPrice = futuresExecQuoteQty / futuresExecQty
			}
		} else {
			futuresExecQty = futuresExecQty2
			futuresExecPrice = futuresExecPrice2
			futuresExecQuoteQty = futuresExecQuoteQty2
		}
		// 合约单有成交，现货也买入对冲
		//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
		//if err != nil {
		//	Error.Println(err)
		//}
		_, binanceExecQty, binanceExecPrice, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty)
		if err != nil {
			Error.Println(err)
		}

		sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
	} else {
		// 将状态转为非持仓状态
		err := sa.stateMachine.ChangeState(State_NotPosition)
		if err != nil {
			Error.Println(err)
		}
	}
}

func (sa *SymbolArbitrage) subProcess_BinanceFilled_NotPosition_FuturesAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	var binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2 float64
	var binanceStatus, binanceStatus2 binance.OrderStatusType
	var binanceErr, binanceErr2 error
	var bBinanceFilled = false
	if sa.binanceLimitOrderId != 0 {
		binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		if binanceStatus == binance.OrderStatusTypeFilled {
			bBinanceFilled = true
		} else {
			Warning.Printf("Binance Order %v status is %v, err is %v\n", sa.binanceLimitOrderId, binanceStatus, binanceErr)
		}
	}
	if sa.binanceAntiLimitOrderId != 0 {
		binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, binanceStatus2, binanceErr2 = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
		if binanceStatus2 == binance.OrderStatusTypeFilled {
			bBinanceFilled = true
		} else {
			Warning.Printf("Binance Order %v status is %v, err is %v\n", sa.binanceAntiLimitOrderId, binanceStatus2, binanceErr2)
		}
	}
	if bBinanceFilled == false {
		return
	}

	// 关闭当前的现货单
	if sa.binanceLimitOrderId != 0 {
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if sa.binanceAntiLimitOrderId != 0 {
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
		if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
			binanceExecQuoteQty += binanceExecQuoteQty2
			binanceExecQty += binanceExecQty2
			binanceExecPrice = binanceExecQuoteQty / binanceExecQty
		}
	} else {
		if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
			binanceExecQuoteQty = binanceExecQuoteQty2
			binanceExecQty = binanceExecQty2
			binanceExecPrice = binanceExecPrice2
		}
	}

	bFuturesNotPosition := false
	if sa.futuresAntiLimitOrderId != 0 {
		_, futuresExecQty, _, futuresStatus, _ := getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		// 如果合约反向单完全成交，则应将状态转为未持仓
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesNotPosition = true
		} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
			sa.subStateFuturesExecQty -= futuresExecQty
		}
	}

	if bFuturesNotPosition {
		// 合约反向单已经成交，此时，需要根据现货单成交数量，在合约开空单
		//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
		//if err != nil {
		//	Error.Println(err)
		//}
		// 将状态转为非持仓状态
		//err = sa.stateMachine.ChangeState(State_NotPosition)
		//if err != nil {
		//	Error.Println(err)
		//}
		_, futuresExecQty, futuresExecPrice, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty)
		if err != nil {
			Error.Println(err)
			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		}
	} else {
		subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
		if subStateFuturesExecQuoteQty-binanceExecQuoteQty < 1.0 && subStateFuturesExecQuoteQty-binanceExecQuoteQty > -1.0 {
			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
		} else if subStateFuturesExecQuoteQty > binanceExecQuoteQty {
			//err := createFuturesBuyOrder(sa.BookTicker.Symbol, sa.subStateFuturesExecQty-binanceExecQty)
			//if err != nil {
			//	Error.Println(err)
			//}
			binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, subStateFuturesExecQuoteQty-binanceExecQuoteQty)
			if err != nil {
				Error.Println(err)
			} else {
				binanceExecQty += binanceExecQty2
				binanceExecQuoteQty += binanceExecQuoteQty2
				binanceExecPrice = binanceExecQuoteQty / binanceExecQty
			}
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)

			// 状态改为持仓
			//sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
		} else {
			futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
			if err != nil {
				Error.Println(err)
			} else {
				subStateFuturesExecQuoteQty += futuresExecQuoteQty2
				sa.subStateFuturesExecQty += futuresExecQty2
				sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
			}

			//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
			//if err != nil {
			//	Error.Println(err)
			//}

			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
		}
	}
}

func (sa *SymbolArbitrage) subProcess_FuturesFilled_NotPosition_InitSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if sa.futuresLimitOrderId == 0 {
		Warning.Println("sa.futuresLimitOrderId == 0")
		return
	}
	_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures Order Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}

	// 判断当前合约单状态，如果此时已经成交，则可以直接转为持仓，如果此时部分成交，则等待全部成交即可
	_, binanceExecQty, binanceExecPrice, binanceStatus, _ := getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
	if binanceStatus == binance.OrderStatusTypeFilled {
		sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		return
	} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
		Info.Printf("BinanceOrder %v is Partially Filled. Please wait\n", sa.binanceLimitOrderId)
		return
	}

	bBinanceMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	binanceBestAskPrice, err := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestAskPrice, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestAskPrice is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}
	binanceBestAskQty, err := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestAskQty, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestAskQty is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}

	if (futuresExecQty-binanceBestAskPrice)/binanceBestAskPrice > conf.GreatCreatePremium &&
		binanceBestAskPrice*binanceBestAskQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bBinanceMarket = true
	} else {
		bBinanceMarket = false
	}

	if bBinanceMarket {
		// 取消当前现货限价单
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(sa.BookTicker.Symbol, conf.QuoteOrderQty)
		if err != nil {
			Error.Println(err)
			bBinanceMarket = false
		} else {
			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		}
	}
	if !bBinanceMarket {
		var priceFuturesPrecision, priceBinancePrecision int
		exchangeInfo, bOK := symbolExchangeInfos[sa.BookTicker.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		priceFuturesPrecision = exchangeInfo.FuturesPricePrecision
		priceBinancePrecision = exchangeInfo.SpotPricePrecision
		sFuturesAntiPrice := strconv.FormatFloat(futuresExecPrice/(1+conf.CreatePremium), 'f', priceFuturesPrecision, 64)
		sBinanceAntiPrice := strconv.FormatFloat(futuresExecPrice/(1+sa.dPremiumStage-0.002), 'f', priceBinancePrecision, 64)
		Info.Println(sFuturesAntiPrice, sBinanceAntiPrice)
		antiFuturesOrderId, err := createFuturesBuyLimitOrder(sa.BookTicker.Symbol, sFuturesAntiPrice, futuresExecQty)
		if err != nil {
			Error.Println(err)
			antiFuturesOrderId = 0
		}
		var antiBinanceOrderId int64
		antiBinanceOrderId = 0
		if sa.dPremiumStage-conf.CreatePremium > 0.002 {
			antiBinanceOrderId, err = createBinanceBuyLimitOrder(sa.BookTicker.Symbol, sBinanceAntiPrice, conf.QuoteOrderQty)
			if err != nil {
				Error.Println(err)
			}
		}
		sa.stateMachine.ChangeSubState(SubState_FuturesAntiCreated, antiBinanceOrderId, antiFuturesOrderId, futuresExecQty, futuresExecPrice)
	}
}

func (sa *SymbolArbitrage) subProcess_FuturesFilled_NotPosition_FuturesAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if sa.futuresAntiLimitOrderId == 0 {
		Warning.Println("futuresAntiLimitOrderId == 0")
		return
	}
	_, _, _, futuresStatus, futuresErr := getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures AntiOrder Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}

	var binanceExecQuoteQty, binanceExecQuoteQty2, binanceExecQty, binanceExecQty2, binanceExecPrice, binanceExecPrice2 float64
	var binanceStatus, binanceStatus2 binance.OrderStatusType
	var binanceErr, binanceErr2 error
	if sa.binanceLimitOrderId != 0 {
		binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if sa.binanceAntiLimitOrderId != 0 {
		binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, binanceStatus2, binanceErr2 = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if binanceErr == nil || binanceStatus == binance.OrderStatusTypePartiallyFilled || binanceErr2 == nil || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
		if binanceErr == nil || binanceStatus == binance.OrderStatusTypePartiallyFilled {
			if binanceErr2 == nil || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				binanceExecQty += binanceExecQty2
				binanceExecQuoteQty += binanceExecQuoteQty2
				binanceExecPrice = binanceExecQuoteQty / binanceExecQty
			}
		} else if binanceErr2 == nil || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
			binanceExecQty = binanceExecQty2
			binanceExecPrice = binanceExecPrice2
		}
		_, futuresExecQty, futuresExecPrice, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty)
		if err != nil {
			Error.Println(err)
		} else {
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		}
		//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
		//if err != nil {
		//	Error.Println(err)
		//}
	} else {
		// 将状态转为非持仓状态
		err := sa.stateMachine.ChangeState(State_NotPosition)
		if err != nil {
			Error.Println(err)
		}
	}
}

func (sa *SymbolArbitrage) subProcess_FuturesFilled_NotPosition_BinanceAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	var futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2 float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	var futuresErr, futuresErr2 error
	var bFuturesFilled = false
	if sa.futuresLimitOrderId != 0 {
		futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", sa.futuresLimitOrderId, futuresStatus, futuresErr)
		}
	}
	if sa.futuresAntiLimitOrderId != 0 {
		futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2, futuresStatus2, futuresErr2 = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		if futuresStatus2 == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", sa.futuresAntiLimitOrderId, futuresStatus2, futuresErr2)
		}
	}
	if bFuturesFilled == false {
		return
	}

	if sa.futuresLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if sa.futuresAntiLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQuoteQty += futuresExecQuoteQty2
			futuresExecQty += futuresExecQty2
			futuresExecPrice = futuresExecQuoteQty / futuresExecQty
		}
	} else {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQuoteQty = futuresExecQuoteQty2
			futuresExecQty = futuresExecQty2
			futuresExecPrice = futuresExecPrice2
		}
	}

	bBinanceNotPosition := false
	if sa.binanceAntiLimitOrderId != 0 {
		_, binanceExecQty, _, binanceStatus, _ := getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		// 如果合约反向单完全成交，则应将状态转为未持仓
		if binanceStatus == binance.OrderStatusTypeFilled {
			bBinanceNotPosition = true
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
			sa.subStateBinanceExecQty -= binanceExecQty
		}
	}

	if bBinanceNotPosition {
		_, binanceExecQty, binanceExecPrice, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty)
		if err != nil {
			Error.Println(err)
		} else {
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, binanceExecPrice, futuresExecQty, futuresExecPrice)
		}
		//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
		//if err != nil {
		//	Error.Println(err)
		//}
		// 将状态转为非持仓状态
		//err = sa.stateMachine.ChangeState(State_NotPosition)
		//if err != nil {
		//	Error.Println(err)
		//}
	} else {
		subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
		if subStateBinanceExecQuoteQty-futuresExecQuoteQty < 1.0 && subStateBinanceExecQuoteQty-futuresExecQuoteQty > -1.0 {
			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
		} else if subStateBinanceExecQuoteQty > futuresExecQuoteQty {
			//err := createBinanceSellOrder(sa.BookTicker.Symbol, sa.subStateBinanceExecQty-futuresExecQty)
			//if err != nil {
			//	Error.Println(err)
			//}
			futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, sa.subStateBinanceExecQty-futuresExecQty)
			if err != nil {
				Error.Println(err)
			} else {
				futuresExecQuoteQty += futuresExecQuoteQty2
				futuresExecQty += futuresExecQty2
				futuresExecPrice = futuresExecQuoteQty / futuresExecQty
			}

			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
		} else {
			//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-sa.subStateBinanceExecQty)
			//if err != nil {
			//	Error.Println(err)
			//}
			binanceExecQuoteQty, binanceExecQty, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty-subStateBinanceExecQuoteQty)
			if err != nil {
				Error.Println(err)
			} else {
				subStateBinanceExecQuoteQty += binanceExecQuoteQty
				sa.subStateBinanceExecQty += binanceExecQty
				sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
			}

			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
		}
	}
}

func (sa *SymbolArbitrage) subProcess_BinanceFilled_Position_InitSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance Order Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	// 判断当前合约单状态，如果此时已经成交，则可以直接转为持仓，如果此时部分成交，则等待全部成交即可
	_, _, _, futuresStatus, _ := getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
	if futuresStatus == futures.OrderStatusTypeFilled {
		// 将状态转为非持仓状态
		err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
		if err != nil {
			Error.Println(err)
		}
		err = sa.stateMachine.ChangeState(State_NotPosition)
		if err != nil {
			Error.Println(err)
		}
		return
	} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
		Info.Printf("FuturesOrder %v is Partially Filled. Please wait\n", sa.futuresLimitOrderId)
		return
	}

	bFuturesMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	futuresBestAskPrice, err := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestAskPrice, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestAskPrice is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}
	futuresBestAskQty, err := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestAskQty, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestAskQty is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}

	if (futuresBestAskPrice-binanceExecPrice)/binanceExecPrice < conf.GreatClosePremium &&
		futuresBestAskPrice*futuresBestAskQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bFuturesMarket = true
	} else {
		bFuturesMarket = false
	}

	if bFuturesMarket {
		// 创建合约市价单，并取消合约挂单
		// 取消当前合约限价单
		err := cancelFuturesLimitOrder(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		err = createFuturesBuyOrder(sa.symbolPosition.Symbol, sa.symbolPosition.FutureCount)
		if err != nil {
			Error.Println(err)
			bFuturesMarket = false
		} else {
			// 将状态转为非持仓状态
			err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}
			// 将状态转为非持仓状态
			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		}
	}
	if !bFuturesMarket {
		//cummuQuoteQty, _ := strconv.ParseFloat(tmpBinanceFilledOrder.CummuQuoteQty, 64)
		//executedQty, _ := strconv.ParseFloat(tmpBinanceFilledOrder.ExecutedQty, 64)
		//avgPrice := cummuQuoteQty / executedQty
		var spotPricePrecision, futuresPricePrecision int
		exchangeInfo, bOK := symbolExchangeInfos[sa.symbolPosition.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		spotPricePrecision = exchangeInfo.SpotPricePrecision
		futuresPricePrecision = exchangeInfo.FuturesPricePrecision
		sBinanceAntiPrice := strconv.FormatFloat(binanceExecPrice/(1+conf.CreatePremium), 'f', spotPricePrecision, 64)
		sFuturesAntiPrice := strconv.FormatFloat(binanceExecPrice*(1+conf.ClosePremium), 'f', futuresPricePrecision, 64)
		Info.Println(sBinanceAntiPrice, sFuturesAntiPrice)
		antiBinanceOrderId, err := createBinanceBuyLimitOrder(sa.symbolPosition.Symbol, sBinanceAntiPrice, binanceExecQuoteQty/(1+conf.CreatePremium))
		if err != nil {
			Error.Println(err)
			antiBinanceOrderId = 0
		}
		antiFuturesOrderId, err := createFuturesBuyLimitOrder(sa.symbolPosition.Symbol, sFuturesAntiPrice, sa.symbolPosition.FutureCount)
		if err != nil {
			Error.Println(err)
			antiFuturesOrderId = 0
		}
		sa.stateMachine.ChangeSubState(SubState_BinanceAntiCreated, antiBinanceOrderId, antiFuturesOrderId, binanceExecQty, binanceExecPrice)
	}
}

func (sa *SymbolArbitrage) subProcess_BinanceFilled_Position_BinanceAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	if sa.binanceAntiLimitOrderId == 0 {
		Warning.Println("binanceAntiLimitOrderId == 0")
		return
	}
	_, _, _, binanceStatus, binanceErr := getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceAntiLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance AntiOrder Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	var futuresExecQuoteQty, futuresExecQuoteQty2, futuresExecQty, futuresExecQty2, futuresExecPrice float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	// 将合约单取消
	if sa.futuresLimitOrderId != 0 {
		futuresExecQuoteQty, futuresExecQty, _, futuresStatus, _ = getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
		err := cancelFuturesLimitOrder(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将创建的合约适配单取消
	if sa.futuresAntiLimitOrderId != 0 {
		futuresExecQuoteQty2, futuresExecQty2, _, futuresStatus2, _ = getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(sa.symbolPosition.Symbol, sa.futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	// 如果合约单有成交，平掉
	if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQty += futuresExecQty2
			futuresExecQuoteQty += futuresExecQuoteQty2
			futuresExecPrice = futuresExecQuoteQty / futuresExecQty
		}
		_, _, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice, futuresExecQuoteQty)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将状态转为持仓状态
	err := sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
	if err != nil {
		Error.Println(err)
	}
}

func (sa *SymbolArbitrage) subProcess_BinanceFilled_Position_FuturesAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	if sa.binanceLimitOrderId == 0 {
		Error.Println("binanceLimitOrderId == 0")
		return
	}

	_, _, _, binanceStatus, binanceErr := getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance Order %v status is %v, err is %v\n", sa.binanceLimitOrderId, binanceStatus, binanceErr)
		return
	}

	// 关闭当前的现货单
	err := cancelBinanceLimitOrder(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
	if err != nil {
		Error.Println(err)
	}

	if sa.futuresAntiLimitOrderId != 0 {
		_, futuresExecQty, _, futuresStatus, _ := getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(sa.symbolPosition.Symbol, sa.futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		// 如果合约反向单完全成交，则应将状态转为未持仓
		if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
			err = createFuturesBuyOrder(sa.symbolPosition.Symbol, futuresExecQty)
			if err != nil {
				Error.Println(err)
			}
		}
	}

	// 将状态转为非持仓状态
	err = ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
	if err != nil {
		Error.Println(err)
	}

	err = sa.stateMachine.ChangeState(State_NotPosition)
	if err != nil {
		Error.Println(err)
	}
}

func (sa *SymbolArbitrage) subProcess_FuturesFilled_Position_InitSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if sa.futuresLimitOrderId == 0 {
		Error.Println("futuresLimitOrderId == 0")
		return
	}
	_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures Order Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}
	if sa.binanceLimitOrderId != 0 {
		_, _, _, binanceStatus, _ := getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
		if binanceStatus == binance.OrderStatusTypeFilled {
			// 将状态转为非持仓状态
			err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}

			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
			return
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
			Info.Printf("BinanceOrder %v is Partially Filled. Please wait\n", sa.binanceLimitOrderId)
			return
		}
	}

	bBinanceMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	binanceBestBidPrice, err := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestBidPrice, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestBidPrice is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}
	binanceBestBidQty, err := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestBidQty, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestBidQty is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}

	if (futuresExecPrice-binanceBestBidPrice)/binanceBestBidPrice < conf.GreatClosePremium &&
		binanceBestBidPrice*binanceBestBidQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bBinanceMarket = true
	} else {
		bBinanceMarket = false
	}

	if bBinanceMarket {
		err := cancelBinanceLimitOrder(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}

		err = createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount)
		if err != nil {
			Error.Println(err)
			bBinanceMarket = false
		} else {
			// 将状态转为持仓状态
			err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}

			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		}
	}
	if !bBinanceMarket {
		var pricePrecision int
		exchangeInfo, bOK := symbolExchangeInfos[sa.symbolPosition.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		pricePrecision = exchangeInfo.FuturesPricePrecision
		sAntiPrice := strconv.FormatFloat(futuresExecPrice*(1+conf.CreatePremium), 'f', pricePrecision, 64)
		antiOrderId, err := createFuturesSellLimitOrder(sa.symbolPosition.Symbol, sAntiPrice, futuresExecQty)
		if err != nil {
			Error.Println(err)
		}
		sa.stateMachine.ChangeSubState(SubState_FuturesAntiCreated, int64(0), antiOrderId, futuresExecQty, futuresExecPrice)
	}
}

func (sa *SymbolArbitrage) subProcess_FuturesFilled_Position_FuturesAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if sa.futuresAntiLimitOrderId == 0 {
		Error.Println("futuresAntiLimitOrderId == 0")
		return
	}
	_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresAntiLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures AntiOrder Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}

	binanceExecQuoteQty, _, _, binanceStatus, _ := getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
	err := cancelBinanceLimitOrder(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
	if err != nil {
		Error.Println(err)
	}
	if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
		_, _, _, err := createBinanceBuyOrder(sa.symbolPosition.Symbol, binanceExecQuoteQty)
		if err != nil {
			Error.Println(err)
		}
	}
	// 更新数据库
	// Todo
	// 将状态转为非持仓状态
	sa.symbolPosition.FuturePrice = futuresExecPrice
	sa.symbolPosition.FutureCount = futuresExecQty
	err = sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
	if err != nil {
		Error.Println(err)
	}
}

func (sa *SymbolArbitrage) subProcess_FuturesFilled_Position_BinanceAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	var futuresExecQty, futuresExecPrice, futuresExecQty2, futuresExecPrice2, binanceExecQty float64
	var binanceStatus binance.OrderStatusType
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	var futuresErr, futuresErr2 error
	var bFuturesFilled = false
	if sa.futuresLimitOrderId != 0 {
		_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr = getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", sa.futuresLimitOrderId, futuresStatus, futuresErr)
		}
	}
	if sa.futuresAntiLimitOrderId != 0 {
		_, futuresExecQty2, futuresExecPrice2, futuresStatus2, futuresErr2 = getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresAntiLimitOrderId)
		if futuresStatus2 == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", sa.futuresAntiLimitOrderId, futuresStatus2, futuresErr2)
		}
	}
	if bFuturesFilled == false {
		return
	}

	if sa.futuresLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if sa.futuresAntiLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	if sa.binanceAntiLimitOrderId != 0 {
		_, binanceExecQty, _, binanceStatus, _ = getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceAntiLimitOrderId)
		err := cancelBinanceLimitOrder(sa.symbolPosition.Symbol, sa.binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
		err := createBinanceSellOrder(sa.symbolPosition.Symbol, binanceExecQty)
		if err != nil {
			Error.Println(err)
		}
	}

	bFuturesOverBuy := false
	if futuresStatus == futures.OrderStatusTypeFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			bFuturesOverBuy = true
			futuresExecQty = futuresExecQty2
			futuresExecPrice = futuresExecPrice2
		}
	} else if futuresStatus2 == futures.OrderStatusTypeFilled {
		if futuresStatus == futures.OrderStatusTypePartiallyFilled {
			bFuturesOverBuy = true
		}
	}
	if bFuturesOverBuy {
		_, _, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice, futuresExecQty)
		if err != nil {
			Error.Println(err)
		}
	}

	// 将状态转为非持仓状态
	err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
	if err != nil {
		Error.Println(err)
	}

	err = sa.stateMachine.ChangeState(State_NotPosition)
	if err != nil {
		Error.Println(err)
	}
}

func (sa *SymbolArbitrage) timeoutNotPosition() {
	if sa.stateMachine.SubState == SubState_Init {
		binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, _ := getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ := getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		// 取消当前订单
		err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		err = cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		if binanceStatus == binance.OrderStatusTypeFilled && futuresStatus == futures.OrderStatusTypeFilled {
			// 状态改为持仓
			sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		} else if binanceStatus == binance.OrderStatusTypeFilled {
			if futuresStatus != futures.OrderStatusTypePartiallyFilled {
				//futuresBestBidPrice, _ := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestBidPrice, 64)
				//if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
				var err error
				//_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(sa.BookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty)
				_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty)
				if err != nil {
					err = createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
				//} else {
				//	err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
				//	if err != nil {
				//		Error.Println(err)
				//	}

				//	err = sa.stateMachine.ChangeState(State_NotPosition)
				//	if err != nil {
				//		Error.Println(err)
				//	}
				//}
			} else {
				//futuresBestBidPrice, _ := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestBidPrice, 64)
				//if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
				//	futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder(sa.BookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty-futuresExecQuoteQty)
				futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty-futuresExecQty)
				if err != nil {
					err = createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, futuresExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				} else {
					futuresExecQuoteQty += futuresExecQuoteQty2
					futuresExecQty += futuresExecQty2
					futuresExecPrice = futuresExecQuoteQty / futuresExecQty

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
				//} else {
				//	err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-futuresExecQty)
				//	if err != nil {
				//		Error.Println(err)
				//	}

				//	// 状态改为持仓
				//	sa.changeState2Position(sa.BookTicker.Symbol, futuresExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				//}
			}
		} else if futuresStatus == futures.OrderStatusTypeFilled {
			if binanceStatus != binance.OrderStatusTypePartiallyFilled {
				//binanceBestAskPrice, _ := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestAskPrice, 64)
				//if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
				var err error
				_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(sa.BookTicker.Symbol, conf.QuoteOrderQty)
				if err != nil {
					err = createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
				//} else {
				//	err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
				//	if err != nil {
				//		Error.Println(err)
				//	}

				//	err = sa.stateMachine.ChangeState(State_NotPosition)
				//	if err != nil {
				//		Error.Println(err)
				//	}
				//}
			} else {
				//binanceBestAskPrice, _ := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestAskPrice, 64)
				//if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
				binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, conf.QuoteOrderQty-binanceExecQuoteQty)
				if err != nil {
					err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, futuresExecPrice)
				} else {
					binanceExecQuoteQty += binanceExecQuoteQty2
					binanceExecQty += binanceExecQty2
					binanceExecPrice = binanceExecQuoteQty / binanceExecQty

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
				//} else {
				//	err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-binanceExecQty)
				//	if err != nil {
				//		Error.Println(err)
				//	}

				//	// 状态改为持仓
				//	sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, futuresExecPrice)
				//}
			}
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
			if futuresStatus != futures.OrderStatusTypePartiallyFilled {
				//futuresBestBidPrice, _ := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestBidPrice, 64)
				//if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
				var err error
				//_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(sa.BookTicker.Symbol, futuresBestBidPrice, binanceExecQuoteQty)
				_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty)
				if err != nil {
					err = createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
				//} else {
				//	err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
				//	if err != nil {
				//		Error.Println(err)
				//	}

				//	err = sa.stateMachine.ChangeState(State_NotPosition)
				//	if err != nil {
				//		Error.Println(err)
				//	}
				//}
			} else if binanceStatus != binance.OrderStatusTypePartiallyFilled {
				//binanceBestAskPrice, _ := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestAskPrice, 64)
				//if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
				var err error
				_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty)
				if err != nil {
					err = createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
				//} else {
				//	err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
				//	if err != nil {
				//		Error.Println(err)
				//	}

				//	err = sa.stateMachine.ChangeState(State_NotPosition)
				//	if err != nil {
				//		Error.Println(err)
				//	}
				//}
			} else {
				if binanceExecQuoteQty-futuresExecQuoteQty < 1.0 && binanceExecQuoteQty-futuresExecQuoteQty > -1.0 {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				} else if binanceExecQuoteQty > futuresExecQuoteQty {
					futuresBestBidPrice, _ := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestBidPrice, 64)
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder(sa.BookTicker.Symbol, futuresBestBidPrice, binanceExecQuoteQty-futuresExecQuoteQty)
					if err != nil {
						Error.Println(err)
						err = createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-futuresExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, futuresExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					} else {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty-binanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
						err = createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-binanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, futuresExecPrice)
					} else {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				}
			}
		} else {
			err := sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		}
	} else if sa.stateMachine.SubState == SubState_BinanceAntiCreated {
		var binanceExecQuoteQty, binanceExecQty, futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2 float64
		var binanceStatus binance.OrderStatusType
		var futuresStatus, futuresStatus2 futures.OrderStatusType
		if sa.binanceAntiLimitOrderId != 0 {
			binanceExecQuoteQty, binanceExecQty, _, binanceStatus, _ = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
			err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.futuresLimitOrderId != 0 {
			futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
			err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.futuresAntiLimitOrderId != 0 {
			futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2, futuresStatus2, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}

		// 处理其他逻辑
		if binanceStatus == binance.OrderStatusTypeFilled {
			// 合约有成交，平掉合约成交的部分
			if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
					if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
					}
				} else if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
					futuresExecQuoteQty = futuresExecQuoteQty2
					futuresExecQty = futuresExecQty2
					futuresExecPrice = futuresExecPrice2
				}
				_, binanceExecQty, binanceExecPrice, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty)
				if err != nil {
					Error.Println(err)
				} else {
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
			} else {
				// 将状态变为未持仓
				err := sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			}
		} else {
			if binanceStatus == binance.OrderStatusTypePartiallyFilled {
				//subStateBinanceExecQuoteQty := subStateBinanceExecPrice * subStateBinanceExecQty
				//subStateBinanceExecQuoteQty -= binanceExecQuoteQty
				sa.subStateBinanceExecQty -= binanceExecQty
				//subStateBinanceExecPrice = subStateBinanceExecQuoteQty / subStateBinanceExecQty
			}

			// 判断合约单是否有成交的，如果有判断跟当前的现货单关系
			if futuresStatus == futures.OrderStatusTypeFilled {
				if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if binanceStatus == binance.OrderStatusTypePartiallyFilled {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
						//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-sa.subStateBinanceExecQty)
						//if err != nil {
						//	Error.Println(err)
						//}
						subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
						binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty-subStateBinanceExecQuoteQty)
						if err != nil {
							Error.Println(err)
						} else {
							sa.subStateBinanceExecQty += binanceExecQty2
							subStateBinanceExecQuoteQty += binanceExecQuoteQty2
							sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
					} else {
						//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty2)
						//if err != nil {
						//	Error.Println(err)
						//}
						binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty2)
						if err != nil {
							Error.Println(err)
						} else {
							subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
							sa.subStateBinanceExecQty += binanceExecQty2
							subStateBinanceExecQuoteQty += binanceExecQuoteQty2
							sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
					}
				} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-sa.subStateBinanceExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, binanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
					} else {
						subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty*sa.subStateBinanceExecPrice + binanceExecQuoteQty2
						sa.subStateBinanceExecQty += binanceExecQty2
						sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
				}
			} else if futuresStatus2 == futures.OrderStatusTypeFilled {
				if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if binanceStatus == binance.OrderStatusTypePartiallyFilled {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
						//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-sa.subStateBinanceExecQty)
						//if err != nil {
						//	Error.Println(err)
						//}
						subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
						binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty-subStateBinanceExecQuoteQty)
						if err != nil {
							Error.Println(err)
						} else {
							subStateBinanceExecQuoteQty += binanceExecQuoteQty2
							sa.subStateBinanceExecQty += binanceExecQty2
							sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
					} else {
						//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty)
						//if err != nil {
						//	Error.Println(err)
						//}
						binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty)
						if err != nil {
							Error.Println(err)
						} else {
							subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
							subStateBinanceExecQuoteQty += binanceExecQuoteQty2
							sa.subStateBinanceExecQty += binanceExecQty2
							sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty+futuresExecQty2, sa.subStateBinanceExecPrice, futuresExecPrice2)
					}
				} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty2-sa.subStateBinanceExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, binanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
					} else {
						subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
						subStateBinanceExecQuoteQty += binanceExecQuoteQty2
						sa.subStateBinanceExecQty += binanceExecQty2
						sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty2, sa.subStateBinanceExecPrice, futuresExecPrice2)
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty2, sa.subStateBinanceExecPrice, futuresExecPrice2)
				}
			} else if futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					if futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
					}
				} else {
					futuresExecQuoteQty = futuresExecQuoteQty2
					futuresExecQty = futuresExecQty2
					futuresExecPrice = futuresExecPrice2
				}
				subStateBinanceExecQuoteQty := sa.subStateBinanceExecQty * sa.subStateBinanceExecPrice
				if subStateBinanceExecQuoteQty-futuresExecQuoteQty < 1.0 && subStateBinanceExecQuoteQty-futuresExecQuoteQty > -1.0 {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
				} else if subStateBinanceExecQuoteQty > futuresExecQuoteQty {
					//err := createBinanceSellOrder(sa.BookTicker.Symbol, sa.subStateBinanceExecQty-futuresExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, sa.subStateBinanceExecQty-futuresExecQty)
					if err != nil {
						Error.Println(err)
					} else {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
				} else {
					//err := createFuturesBuyOrder(sa.BookTicker.Symbol, futuresExecQty-sa.subStateBinanceExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, futuresExecQuoteQty-subStateBinanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
					} else {
						subStateBinanceExecQuoteQty += binanceExecQuoteQty2
						sa.subStateBinanceExecQty += binanceExecQty2
						sa.subStateBinanceExecPrice = subStateBinanceExecQuoteQty / sa.subStateBinanceExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
				}
			} else {
				//err := createBinanceSellOrder(sa.BookTicker.Symbol, sa.subStateBinanceExecQty)
				//if err != nil {
				//	Error.Println(err)
				//}
				_, futuresExecQty, futuresExecPrice, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, sa.subStateBinanceExecQty)
				if err != nil {
					Error.Println(err)
					err = createBinanceSellOrder(sa.BookTicker.Symbol, sa.subStateBinanceExecQty)
					if err != nil {
						Error.Println(err)
					}
					// 将状态变为未持仓
					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					sa.changeState2Position(sa.BookTicker.Symbol, sa.subStateBinanceExecQty, futuresExecQty, sa.subStateBinanceExecPrice, futuresExecPrice)
				}
			}
		}
	} else if sa.stateMachine.SubState == SubState_FuturesAntiCreated {
		var binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, futuresExecQty float64
		var binanceStatus, binanceStatus2 binance.OrderStatusType
		var futuresStatus futures.OrderStatusType
		if sa.binanceLimitOrderId != 0 {
			binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, _ = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
			err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.binanceAntiLimitOrderId != 0 {
			binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, binanceStatus2, _ = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
			err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.futuresAntiLimitOrderId != 0 {
			_, futuresExecQty, _, futuresStatus, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}

		// 处理其他逻辑
		if futuresStatus == futures.OrderStatusTypeFilled {
			if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled || binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
					if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
					}
				} else {
					binanceExecQuoteQty = binanceExecQuoteQty2
					binanceExecQty = binanceExecQty2
					binanceExecPrice = binanceExecPrice2
				}
				_, futuresExecQty, futuresExecPrice, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty)
				if err != nil {
					Error.Println(err)
					err = createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}
					// 将状态变为未持仓
					err := sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
			} else {
				// 将状态变为未持仓
				err := sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			}
		} else {
			if futuresStatus == futures.OrderStatusTypePartiallyFilled {
				//subStateFuturesExecQuoteQty := subStateFuturesExecPrice * subStateFuturesExecQty
				//subStateFuturesExecQuoteQty -= futuresExecQuoteQty
				sa.subStateFuturesExecQty -= futuresExecQty
				//subStateFuturesExecPrice = subStateFuturesExecQuoteQty / subStateFuturesExecQty
			}

			// 判断现货单是否有成交的，如果有判断跟当前的合约单关系
			if binanceStatus == binance.OrderStatusTypeFilled {
				if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if futuresStatus == futures.OrderStatusTypePartiallyFilled {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
						//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
						//if err != nil {
						//	Error.Println(err)
						//}
						futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
						if err != nil {
							Error.Println(err)
						} else {
							subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
							subStateFuturesExecQuoteQty += futuresExecQuoteQty2
							sa.subStateFuturesExecQty += futuresExecQty2
							sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
					} else {
						//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty2)
						//if err != nil {
						//	Error.Println(err)
						//}
						futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty2)
						if err != nil {
							Error.Println(err)
						} else {
							subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
							subStateFuturesExecQuoteQty += futuresExecQuoteQty2
							sa.subStateFuturesExecQty += futuresExecQty2
							sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty+binanceExecQty2, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
					}
				} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, futuresExecQty)
					if err != nil {
						Error.Println(err)
					} else {
						subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
						subStateFuturesExecQuoteQty += futuresExecQuoteQty2
						sa.subStateFuturesExecQty += futuresExecQty2
						sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
				}
			} else if binanceStatus2 == binance.OrderStatusTypeFilled {
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if futuresStatus == futures.OrderStatusTypePartiallyFilled {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
						//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
						//if err != nil {
						//	Error.Println(err)
						//}
						futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
						if err != nil {
							Error.Println(err)
						} else {
							subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
							subStateFuturesExecQuoteQty += futuresExecQuoteQty2
							sa.subStateFuturesExecQty += futuresExecQty2
							sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
					} else {
						//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty)
						//if err != nil {
						//	Error.Println(err)
						//}
						futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty)
						if err != nil {
							Error.Println(err)
						} else {
							subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
							subStateFuturesExecQuoteQty += futuresExecQuoteQty2
							sa.subStateFuturesExecQty += futuresExecQty2
							sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
						}

						// 状态改为持仓
						sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty+binanceExecQty2, sa.subStateFuturesExecQty, binanceExecPrice2, sa.subStateFuturesExecPrice)
					}
				} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty2-sa.subStateFuturesExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, futuresExecQty)
					if err != nil {
						Error.Println(err)
					} else {
						subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
						subStateFuturesExecQuoteQty += futuresExecQuoteQty2
						sa.subStateFuturesExecQty += futuresExecQty2
						sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty2, sa.subStateFuturesExecQty, binanceExecPrice2, sa.subStateFuturesExecPrice)
				} else {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty2, sa.subStateFuturesExecQty, binanceExecPrice2, sa.subStateFuturesExecPrice)
				}
			} else if binanceStatus == binance.OrderStatusTypePartiallyFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					if binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
					}
				} else {
					binanceExecQuoteQty = binanceExecQuoteQty2
					binanceExecQty = binanceExecQty2
					binanceExecPrice = binanceExecPrice2
				}
				subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
				if subStateFuturesExecQuoteQty-binanceExecQuoteQty < 1.0 && subStateFuturesExecQuoteQty-binanceExecQuoteQty > -1.0 {
					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
				} else if subStateFuturesExecQuoteQty > binanceExecQuoteQty {
					//err := createFuturesBuyOrder(sa.BookTicker.Symbol, sa.subStateFuturesExecQty-binanceExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(sa.BookTicker.Symbol, subStateFuturesExecQuoteQty-binanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
					} else {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
				} else {
					//err := createBinanceSellOrder(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
					//if err != nil {
					//	Error.Println(err)
					//}
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder_v2(sa.BookTicker.Symbol, binanceExecQty-sa.subStateFuturesExecQty)
					if err != nil {
						Error.Println(err)
					} else {
						subStateFuturesExecQuoteQty += futuresExecQuoteQty2
						sa.subStateFuturesExecQty += futuresExecQty2
						sa.subStateFuturesExecPrice = subStateFuturesExecQuoteQty / sa.subStateFuturesExecQty
					}

					// 状态改为持仓
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
				}
			} else {
				subStateFuturesExecQuoteQty := sa.subStateFuturesExecQty * sa.subStateFuturesExecPrice
				_, binanceExecQty, binanceExecPrice, err := createBinanceBuyOrder(sa.BookTicker.Symbol, subStateFuturesExecQuoteQty)
				if err != nil {
					Error.Println(err)
					err = createFuturesBuyOrder(sa.BookTicker.Symbol, sa.subStateFuturesExecQty)
					if err != nil {
						Error.Println(err)
					}
					// 将状态变为未持仓
					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					sa.changeState2Position(sa.BookTicker.Symbol, binanceExecQty, sa.subStateFuturesExecQty, binanceExecPrice, sa.subStateFuturesExecPrice)
				}
			}
		}
	} else {
		Error.Printf("Unknow SubState %v\n", sa.stateMachine.SubState)
	}
}

func (sa *SymbolArbitrage) timeoutPosition() {
	if sa.stateMachine.SubState == SubState_Init {
		Info.Println(sa.stateMachine.SubState, sa.binanceAntiLimitOrderId, sa.futuresAntiLimitOrderId)
		_, binanceExecQty, binanceExecPrice, binanceStatus, _ := getBinanceOrderInf(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
		_, futuresExecQty, futuresExecPrice, futuresStatus, _ := getFuturesOrderInf(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
		// 取消现货和合约单
		err := cancelBinanceLimitOrder(sa.symbolPosition.Symbol, sa.binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		err = cancelFuturesLimitOrder(sa.symbolPosition.Symbol, sa.futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}

		if binanceStatus == binance.OrderStatusTypeFilled && futuresStatus == futures.OrderStatusTypeFilled {
			err = ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}

			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else if binanceStatus == binance.OrderStatusTypeFilled {
			if futuresStatus != futures.OrderStatusTypePartiallyFilled {
				futuresBestAskPrice, _ := strconv.ParseFloat(sa.BookTicker.FuturesBookTicker.BestAskPrice, 64)
				if (futuresBestAskPrice-binanceExecPrice)/binanceExecPrice < conf.ClosePremium {
					var err error
					err = createFuturesBuyOrder(sa.symbolPosition.Symbol, sa.symbolPosition.FutureCount)
					if err != nil {
						Error.Println(err)
					} else {
						err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
						if err != nil {
							Error.Println(err)
						}

						err = sa.stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					}
				} else {
					var err error
					err = createFuturesBuyOrder(sa.symbolPosition.Symbol, sa.symbolPosition.FutureCount)
					if err != nil {
						Error.Println(err)
					} else {
						err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
						if err != nil {
							Error.Println(err)
						}

						err = sa.stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					}
				}
			} else {
				var err error
				err = createFuturesBuyOrder(sa.symbolPosition.Symbol, sa.symbolPosition.FutureCount-futuresExecQty)
				if err != nil {
					Error.Println(err)
				} else {
					err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
					if err != nil {
						Error.Println(err)
					}

					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			}
		} else if futuresStatus == futures.OrderStatusTypeFilled {
			if binanceStatus != binance.OrderStatusTypePartiallyFilled {
				binanceBestBidPrice, _ := strconv.ParseFloat(sa.BookTicker.BinanceBookTicker.BestBidPrice, 64)
				if (futuresExecPrice-binanceBestBidPrice)/binanceBestBidPrice < conf.ClosePremium {
					var err error
					err = createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount)
					if err != nil {
						Error.Println(err)
					} else {
						err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
						if err != nil {
							Error.Println(err)
						}

						err = sa.stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					}
				} else {
					var err error
					err = createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount)
					if err != nil {
						Error.Println(err)
					} else {
						err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
						if err != nil {
							Error.Println(err)
						}

						err = sa.stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					}
				}
			} else {
				var err error
				err = createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount-binanceExecQty)
				if err != nil {
					Error.Println(err)
				} else {
					err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
					if err != nil {
						Error.Println(err)
					}

					err = sa.stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			}
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
			if binanceStatus == binance.OrderStatusTypePartiallyFilled {
				err := createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount-binanceExecQty)
				if err != nil {
					Error.Println(err)
				}
			}
			if futuresStatus == futures.OrderStatusTypePartiallyFilled {
				err := createFuturesBuyOrder(sa.symbolPosition.Symbol, sa.symbolPosition.FutureCount-futuresExecQty)
				if err != nil {
					Error.Println(err)
				}
			}
			err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}

			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			err := sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
			if err != nil {
				Error.Println(err)
			}
		}
	} else if sa.stateMachine.SubState == SubState_BinanceAntiCreated {
		var binanceExecQuoteQty, binanceExecQty, futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2 float64
		var binanceStatus binance.OrderStatusType
		var futuresStatus, futuresStatus2 futures.OrderStatusType
		if sa.binanceAntiLimitOrderId != 0 {
			binanceExecQuoteQty, binanceExecQty, _, binanceStatus, _ = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
			err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.futuresLimitOrderId != 0 {
			futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
			err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.futuresAntiLimitOrderId != 0 {
			futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2, futuresStatus2, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}

		if binanceStatus == binance.OrderStatusTypeFilled {
			// 如果合约单有成交，平掉
			if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
					if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
						futuresExecQty += futuresExecQty2
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
					}
				} else if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
					futuresExecQty = futuresExecQty2
					futuresExecPrice = futuresExecPrice2
					futuresExecQuoteQty = futuresExecQuoteQty2
				}
				_, _, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice, futuresExecQuoteQty)
				if err != nil {
					Error.Println(err)
				}
			}
			// 将状态转为持仓状态
			err := sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			if futuresStatus == futures.OrderStatusTypeFilled {
				if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
					_, _, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice2, futuresExecQuoteQty2)
					if err != nil {
						Error.Println(err)
					}
				}
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					err := createBinanceSellOrder(sa.symbolPosition.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}
				}
				err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
				if err != nil {
					Error.Println(err)
				}

				err = sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			} else if futuresStatus2 == futures.OrderStatusTypeFilled {
				if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					_, _, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice, futuresExecQuoteQty)
					if err != nil {
						Error.Println(err)
					}
				}
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					err := createBinanceSellOrder(sa.symbolPosition.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}
				}
				err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
				if err != nil {
					Error.Println(err)
				}

				err = sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			} else if futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					if futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
						futuresExecQty += futuresExecQty2
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
					}
				} else {
					futuresExecQty = futuresExecQty2
					futuresExecQuoteQty = futuresExecQuoteQty2
					futuresExecPrice = futuresExecPrice2
				}
				if futuresExecQty < sa.symbolPosition.FutureCount {
					err := createFuturesBuyOrder(sa.symbolPosition.Symbol, sa.symbolPosition.FutureCount-futuresExecQty)
					if err != nil {
						Error.Println(err)
					}
				} else {
					_, _, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice, futuresExecPrice*(futuresExecQty-sa.symbolPosition.FutureCount))
					if err != nil {
						Error.Println(err)
					}
				}
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					err := createBinanceSellOrder(sa.symbolPosition.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}
				}
				// 状态改为平仓
				err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
				if err != nil {
					Error.Println(err)
				}

				err = sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
				_, execQty, _, err := createBinanceBuyOrder(sa.symbolPosition.Symbol, conf.QuoteOrderQty-binanceExecQuoteQty)
				if err != nil {
					Error.Println(err)
				} else {
					binanceExecQty += execQty
				}
				sa.symbolPosition.SpotCount = binanceExecQty
				// 将状态转为持仓状态
				err = sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
				if err != nil {
					Error.Println(err)
				}
			} else {
				_, binanceExecQty, binanceExecPrice, err := createBinanceBuyOrder(sa.symbolPosition.Symbol, conf.QuoteOrderQty)
				if err != nil {
					Error.Println(err)
				} else {
					sa.symbolPosition.SpotCount = binanceExecQty
					sa.symbolPosition.SpotPrice = binanceExecPrice
					// 将状态转为持仓状态
					err = sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			}
		}
	} else if sa.stateMachine.SubState == SubState_FuturesAntiCreated {
		var binanceExecQuoteQty, binanceExecQty, binanceExecPrice, futuresExecQuoteQty, futuresExecQty, futuresExecPrice float64
		var binanceStatus binance.OrderStatusType
		var futuresStatus futures.OrderStatusType
		if sa.binanceLimitOrderId != 0 {
			binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, _ = getBinanceOrderInf(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
			err := cancelBinanceLimitOrder(sa.BookTicker.Symbol, sa.binanceLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if sa.futuresAntiLimitOrderId != 0 {
			futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ = getFuturesOrderInf(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(sa.BookTicker.Symbol, sa.futuresAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}

		if binanceStatus == binance.OrderStatusTypeFilled {
			// 如果现货单成交，平掉
			if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
				err := createFuturesBuyOrder(sa.symbolPosition.Symbol, futuresExecQty)
				if err != nil {
					Error.Println(err)
				}
			}
			// 状态改为平仓
			err := ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}

			err = sa.stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			if futuresStatus == futures.OrderStatusTypeFilled {
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					_, quoteQty, _, err := createBinanceBuyOrder(sa.symbolPosition.Symbol, conf.QuoteOrderQty-binanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
					}
					sa.symbolPosition.SpotCount = sa.symbolPosition.SpotCount - binanceExecQty + quoteQty
				}
				// 将状态转为持仓状态
				err := sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
				if err != nil {
					Error.Println(err)
				}
			} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					binanceQuoteQty := (sa.symbolPosition.SpotCount - binanceExecQty) * binanceExecPrice
					if binanceQuoteQty > futuresExecQuoteQty {
						_, quoteQty, _, err := createFuturesSellOrder(sa.symbolPosition.Symbol, futuresExecPrice, binanceQuoteQty-futuresExecQuoteQty)
						if err != nil {
							Error.Println(err)
							sa.symbolPosition.SpotCount = sa.symbolPosition.SpotCount - binanceExecQty
							sa.symbolPosition.FutureCount = futuresExecQty
						} else {
							sa.symbolPosition.SpotCount = sa.symbolPosition.SpotCount - binanceExecQty
							sa.symbolPosition.FutureCount = futuresExecQty + quoteQty
						}
					} else {
						_, quoteQty, _, err := createBinanceBuyOrder(sa.symbolPosition.Symbol, futuresExecQuoteQty-binanceQuoteQty)
						if err != nil {
							Error.Println(err)
							sa.symbolPosition.SpotCount = sa.symbolPosition.SpotCount - binanceExecQty
							sa.symbolPosition.FutureCount = futuresExecQty
						} else {
							sa.symbolPosition.SpotCount = sa.symbolPosition.SpotCount - binanceExecQty + quoteQty
							sa.symbolPosition.FutureCount = futuresExecQty
						}
					}
				} else {
					err := createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount-futuresExecQty)
					if err != nil {
						Error.Println(err)
						sa.symbolPosition.FutureCount = futuresExecQty
					} else {
						sa.symbolPosition.SpotCount = futuresExecQty
						sa.symbolPosition.FutureCount = futuresExecQty
					}
				}
				// 将状态转为持仓状态
				err := sa.stateMachine.ChangeState(State_Position, sa.symbolPosition)
				if err != nil {
					Error.Println(err)
				}
			} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
				err := createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount-binanceExecQuoteQty)
				if err != nil {
					Error.Println(err)
				}
				// 状态改为平仓
				err = ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
				if err != nil {
					Error.Println(err)
				}

				err = sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			} else {
				err := createBinanceSellOrder(sa.symbolPosition.Symbol, sa.symbolPosition.SpotCount)
				if err != nil {
					Error.Println(err)
				}

				// 状态改为平仓
				err = ppersistence.DeleteArbitragePosition(sa.symbolPosition.Symbol)
				if err != nil {
					Error.Println(err)
				}

				err = sa.stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			}
		}
	} else {
		Error.Printf("Unknow SubState %v\n", sa.stateMachine.SubState)
	}
}
